package other.system.client.sap;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.ScheduleJob;
import com.rkhd.platform.sdk.api.annotations.RequestMethod;
import com.rkhd.platform.sdk.api.annotations.RestApi;
import com.rkhd.platform.sdk.api.annotations.RestMapping;
import com.rkhd.platform.sdk.data.model.Product;
import com.rkhd.platform.sdk.data.model.SyncConfig__c;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.model.BatchOperateResult;
import com.rkhd.platform.sdk.model.OperateResult;
import com.rkhd.platform.sdk.param.ScheduleJobParam;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.service.XObjectService;
import com.rkhd.platform.sdk.service.XoqlService;
import com.rkhd.platform.sdk.task.FutureTask;
import org.apache.commons.lang.StringUtils;
import other.system.client.apitool.SAPClientUtils;
import other.system.client.util.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 对接SAP中间件，获取产品数据 （物料）
 * @Author: 黎炎松
 * @Date: 2024/7/9 09:38
 */
@RestApi(baseUrl = "/xsy/sap")
public class SyncSapProduct implements ScheduleJob, FutureTask {

    private static HCXObjectService hcxObjectService = new HCXObjectService();

    private static XoqlService xoqlService = XoqlService.instance();

    private static final Logger logger = LoggerFactory.getLogger();
    private static final String LOGGER_MSG = "同步SAP产品 ==> ";

    /**
     * 计划作业
     * @param scheduleJobParam
     */
    @Override
    public void execute(ScheduleJobParam scheduleJobParam) {
        try {
            logger.info(LOGGER_MSG + "触发计划作业");
            String messageId = FutureTaskService.instance().addFutureTask(getClass(), "");
            logger.info(LOGGER_MSG + "异步ID:" + messageId);
        } catch (Exception e) {
            logger.error(LOGGER_MSG + " ----- 发生异常：" + e.getMessage());
        }
    }

    /**
     * 异步任务
     * @param s
     * @throws ScriptBusinessException
     */
    @Override
    public void execute(String s) throws ScriptBusinessException {
        logger.info(LOGGER_MSG + "执行异步任务");
        syncProduct();
    }

    /**
     * 手动触发定时任务
     * @return
     */
    @RestMapping(value = "/syncProduct", method = RequestMethod.GET)
    public String handSyncProduct() {
        logger.info(LOGGER_MSG + "手动触发了同步SAP产品事件");
        syncProduct();
        return "同步成功";
    }

    public static void main(String[] args) throws ApiEntityServiceException {
        new SyncSapProduct().syncProduct();
    }

    /**
     * 同步sap物料数据
     */
    public void syncProduct() {
        try {
            logger.info(LOGGER_MSG + "处理开始");

            // 从数据配置表中获取上次更新时间
            String sql = "select id,lastSyncTime__c from syncConfig__c where syncKey__c = 'SAP_PRODUCT_DATA'";
            SyncConfig__c syncConfig = hcxObjectService.queryOne(sql, SyncConfig__c.class);
            if (syncConfig == null) {
                logger.error(LOGGER_MSG + "配置信息不存在");
                return;
            }

            // 获取同步时间
            String startDate = syncConfig.getLastSyncTime__c();
            String endDate = HCDateUtils.dateToString(new Date(), HCDateUtils.FORMAT); // 同步结束时间
            if (StringUtils.isBlank(startDate)) {
                // 如果为空则退回1天前
                startDate = HCDateUtils.getDaysBeforeString(1, HCDateUtils.FORMAT);
            }

            /*
                查询参数
                isErdat: 记录创建日期
                isEndat: 查询终止日期
                isInput：1: 产品分类(一级)/2：产品分类(二级)/3：交付内容(三级)
                正常情况下如果书写了IS_ENDAT会对创建日期和上次更改的日期结合两个入参between查找，没有入IS_ENDAT则会根据IS_ERDAT查找大于创建时间和上次修改的日期
             */
            JSONObject params = new JSONObject();
            params.put("isErdat", startDate); // 2020-01-01
            params.put("isEndat", endDate); // 2026-01-01
            //params.put("delFlag", "X"); // 查询删除的数据  不传则是查询有效的数据
            logger.info(LOGGER_MSG + "params: " + params);

            ResultBody resultBody = SAPClientUtils.sendPost(params, SAPClientUtils.GET_PRODUCT_URL, "");
            logger.info(LOGGER_MSG + "resultBody:" + resultBody);
            if (!Objects.equals(resultBody.getCode(), "200")) {
                logger.error(LOGGER_MSG + "获取SAP产品数据异常:" + resultBody.getMessage());
                return;
            }

            JSONObject result = (JSONObject) resultBody.getResult();
            List<JSONObject> productList = JSONArray.parseArray(result.getString("IT_DATAOUT_DAT"), JSONObject.class);
            logger.info(LOGGER_MSG + "productList: " + productList.size());
            if (productList.size() <= 0) {
                logger.info(LOGGER_MSG + "暂无需要处理的产品数据");
                // 更新同步配置
                syncConfig.setLastSyncTime__c(endDate);
                syncConfig.setLastSyncCount__c(0L);
                hcxObjectService.update(syncConfig);
                return;
            }

            // 根据物料编码进行分组
            Map<String, List<JSONObject>> productListMap = productList.stream().collect(Collectors.groupingBy(e -> e.getString("MATNR")));
            logger.info(LOGGER_MSG + "productListMap: " + productListMap.size());

            // 根据物料编号获取系统中的产品数据 判断是否已经存在
            String matnrIds = productListMap.keySet().stream().collect(Collectors.joining(","));
            sql = "select id,productCode__c from product where enableStatus = 1 and productCode__c in ("  + matnrIds + ")";
            List<JSONObject> crmProductList = xoqlService.query(sql, true).getRecords();
            Map<String, Long> crmProductMap = crmProductList.stream().collect(Collectors.toMap(e -> e.getString("productCode__c"), e1 -> e1.getLong("id"), (e, e1) -> e));
            logger.info(LOGGER_MSG + "crmProductMap: " + crmProductMap.size());

            // 获取通用选项集
            JSONArray taxRatePicks = ComUtils.getGlobalPicks("globalPick83__c");  // 税率
            JSONArray quantityUnitPicks = ComUtils.getGlobalPicks("quantityUnit__c");  // 产品数量单位

            // 获取新增、修改的数据
            List<Product> addProductList = new ArrayList<>();
            List<Product> upProductList = new ArrayList<>();
            for (String matnr : productListMap.keySet()) {
                List<JSONObject> tempList = productListMap.get(matnr);

                Product product = new Product();
                product.setProductSource__c(2); // 产品来源 SAP

                JSONObject productObj = tempList.get(0);

                product.setProductName(productObj.getString("MAKTX")); // 名称
                product.setProductClassificationCode1__c(productObj.getString("ZMC1")); // 产品分类一级编码
                product.setProductClassificationCode2__c(productObj.getString("ZMC2")); // 产品分类二级编码
                product.setProductCategoryL1__c(productObj.getString("ZMC1DEC")); // 产品分类一级描述
                product.setProductCategoryL2__c(productObj.getString("ZMC2DEC")); // 产品分类二级描述
                product.setDeliveryContentCoding__c(productObj.getString("ZMC3")); // 交付内容编码
                product.setExternalMaterialGroup__c(productObj.getString("EXTWG")); // 外部物料组
                product.setExternalMaterialDescription__c(productObj.getString("EWBEZ")); // 外部物料组描述
                product.setProductSX__c(productObj.getString("EWBEZ")); // 产品属性
                product.setLaboratoryDescription__c(productObj.getString("LBTXT")); // 实验室/工程办公室的描述
                product.setFactory__c(productObj.getString("WERKS")); // 工厂
                product.setDescriptionDeliveryContent__c(productObj.getString("ZMC3DEC")); // 交付内容描述
                product.setReservedFields__c(productObj.getString("RSV1")); // 预留字段1
                product.setReservedFields2__c(productObj.getString("RSV2")); // 预留字段2
                product.setReservedFields3__c(productObj.getString("RSV3")); // 预留字段3
                product.setReservedFields4__c(productObj.getString("RSV4")); // 预留字段4
                product.setReservedFields5__c(productObj.getString("RSV5")); // 预留字段5

                // 新增字段 产品领域
                product.setZparea__c(productObj.getString("ZPAREA"));
                product.setZpareazpdec__c(productObj.getString("ZPAREADEC"));

                // 产品形态 (交付内容标识)
                String zmcflag = productObj.getString("ZMCFLAG");
                String productXt = "";
                if (StringUtils.isNotBlank(zmcflag)) {
                    String[] split = zmcflag.split(" ");
                    if (split.length > 1) {
                        productXt = split[1];
                    }
                }
                product.setProductXT__c(productXt);

                // 数量单位
                String meins = productObj.getString("MEINS");
                if (StringUtils.isNotBlank(meins)) {
                    product.setQuantityUnit__c(ComUtils.getGeneralValue(quantityUnitPicks, meins));
                }

                // 产品税率
                String rate = productObj.getString("ZMTAX");
                if (StringUtils.isNotBlank(rate)) {
                    product.setProductTaxRateSap__c(rate); // SAP原始产品税率
                    rate = rate.replace("%", "");
                    product.setProductTaxRate__c(ComUtils.getGeneralValue(taxRatePicks, rate));
                }

                // 判断系统中是否存在，存在则更新
                if (crmProductMap.containsKey(matnr)) {
                    product.setId(crmProductMap.get(matnr));
                    upProductList.add(product);
                } else {
                    // 新增
                    product.setProductCode__c(matnr); // 产品编码
                    product.setEntityType(11010000400001L); // 业务类型
                    product.setParentId(3196810168864007L); // 产品目录
                    addProductList.add(product);
                }

                if (upProductList.size() > 100) {
                    Boolean update = hcxObjectService.batchUpdate(upProductList);
                    System.out.println("update = " + update);
                    upProductList.clear();
                }

            }

            // 批量新增
            if (addProductList.size() > 0) {
                logger.info(LOGGER_MSG + "新增的数据: " + addProductList.size());
                BatchOperateResult batchOperateResult = XObjectService.instance().insert(addProductList, true, true); // 允许部分成功
                if (!batchOperateResult.getSuccess()) {
                    List<OperateResult> operateResults = batchOperateResult.getOperateResults();
                    for (OperateResult operateResult : operateResults) {
                        logger.error(LOGGER_MSG + "批量新增产品数据异常原因:" +  operateResult.getCode() + " => " + operateResult.getErrorMessage() + " => " + operateResult.getDataId());
                    }
                    logger.error(LOGGER_MSG + "批量新增异常: " + batchOperateResult.getErrorMessage());
                    return;
                }
            }

            // 批量修改
            if (upProductList.size() > 0) {
                logger.info(LOGGER_MSG + "修改的数据: " + upProductList.size());
                Boolean update = hcxObjectService.batchUpdate(upProductList);
                if (!update) {
                    logger.error(LOGGER_MSG + "批量修改异常");
                    return;
                }
            }

            // 更新同步配置
            syncConfig.setLastSyncTime__c(endDate);
            syncConfig.setLastSyncCount__c(Long.valueOf(productListMap.size()));
            Boolean update = hcxObjectService.update(syncConfig);
            if (!update) {
                logger.error(LOGGER_MSG + "更新同步配置异常");
                return;
            }

            logger.info(LOGGER_MSG + "处理成功");
        } catch (Exception e) {
            logger.error(LOGGER_MSG + "同步异常: " + e.getMessage());
        }
    }


}
